/**
 ****************************************************************************************************
 * @file        esp_2d.c
 * @author      嵌入式小书虫
 * @version     V1.0
 * @date        2020-04-17
 * @brief       esp_2d 驱动代码
 ****************************************************************************************************
 *
 * 修改说明
 * V1.0 20200417
 * 第一次发布
 <欢迎关注微信公众号：嵌入式小书虫>
 *
 ****************************************************************************************************
 */

#include "esp_2d.h"
#include "esp_2d_disp_adapter.h"
#include "esp_2d_draw.h"
esp_2d_scene_t my_scene;
esp_2d_scene_t my_navigation_scene;

esp_2d_op_t esp_2d_op0;

void esp_2d_init(void){
    __esp_2d_init(&esp_2d_op0);
}
esp_2d_op_t* get_esp_2d_op(){
    return &esp_2d_op0;
}
void __esp_2d_init(esp_2d_op_t* pt_esp_2d_op){ // 初始化 my-2d
    pt_esp_2d_op->state = 0;	
    
    pt_esp_2d_op->scene = &my_scene;
    
    
    //my_2D_op.pfb_size.iWidth = PFB_WIDTH;
    //my_2D_op.pfb_size.iHeight = PFB_HEIGHT;
    pt_esp_2d_op->pfb_region.tSize.iWidth = ESP_2D_PFB_WIDTH;
    pt_esp_2d_op->pfb_region.tSize.iHeight = ESP_2D_PFB_HEIGHT;
    
    pt_esp_2d_op->background_draw_flag = 0;

#if ESP_2D_DIRTY_REGIONS_ENABLE      
    pt_esp_2d_op->DirtyRegions_num = 0;
    pt_esp_2d_op->DirtyRegions_run_num = 0;
#endif  

    s_tHelper_wMSUnit_init();
    
#if ESP_2D_NAVIGATION_SCENE_ENABLE
    pt_esp_2d_op->navigation_scene = &my_navigation_scene;
    __esp_2d_disp_adapter_navigation_scene_init(pt_esp_2d_op,pt_esp_2d_op->navigation_scene);   
#endif    
    
}

void esp_2d_disp_adapter0_task(){
    
    __esp_2d_disp_adapter0_task();
    
}

esp_2d_fsm_rt_t __esp_2d_disp_adapter0_task(void){
    return esp_2d_scene_player_task(&esp_2d_op0);
}

esp_2d_fsm_rt_t esp_2d_draw_all_screen(esp_2d_op_t* pt_esp_2d_op){
    esp_2d_Disp0_DrawBitmap (pt_esp_2d_op->pfb_region.tLocation.iX, 
             pt_esp_2d_op->pfb_region.tLocation.iY, 
             pt_esp_2d_op->pfb_region.tSize.iWidth, 
             pt_esp_2d_op->pfb_region.tSize.iHeight, 
             (uint8_t *)pt_esp_2d_op->pfb_data);
#if ALL_SCREEN_ROW_PRIORITY
    pt_esp_2d_op->pfb_region.tLocation.iY += pt_esp_2d_op->pfb_region.tSize.iHeight; //my_2D_op.pfb_size.iHeight;
        if(pt_esp_2d_op->pfb_region.tLocation.iY >= ESP_2D_LCD_HEIGHT){
            //my_2D_op.state = 0;	
            return esp_2d_fsm_rt_cpl;
        }
#else    
    pt_esp_2d_op->pfb_region.tLocation.iX +=  pt_esp_2d_op->pfb_region.tSize.iWidth;//   my_2D_op.pfb_size.iWidth;
    if(pt_esp_2d_op->pfb_region.tLocation.iX >= ESP_2D_LCD_WIDTH){
        pt_esp_2d_op->pfb_region.tLocation.iX = 0;                
        pt_esp_2d_op->pfb_region.tLocation.iY += pt_esp_2d_op->pfb_region.tSize.iHeight; //my_2D_op.pfb_size.iHeight;
        if(pt_esp_2d_op->pfb_region.tLocation.iY >= ESP_2D_LCD_HEIGHT){
            //my_2D_op.state = 0;	
            return esp_2d_fsm_rt_cpl;
        }
    }
#endif    
    return esp_2d_fsm_rt_on_going;
}

#if ESP_2D_DIRTY_REGIONS_ENABLE  
void calculate_pfb_DirtyRegion(esp_2d_op_t* pt_esp_2d_op){
    //uint16_t num = PFB_SIZE / my_2D_op.ptDirtyRegions[0].tSize.iWidth;
    pt_esp_2d_op->pfb_region.tLocation.iX = pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tLocation.iX;
    pt_esp_2d_op->pfb_region.tLocation.iY = pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tLocation.iY;
    //行优先
    if(pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tSize.iWidth > ESP_2D_PFB_SIZE){
        pt_esp_2d_op->pfb_region.tSize.iWidth = ESP_2D_PFB_SIZE;
        pt_esp_2d_op->pfb_region.tSize.iHeight = 1;
        pt_esp_2d_op->Row_priority_flag = 1;
    }else{
        pt_esp_2d_op->pfb_region.tSize.iWidth = pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tSize.iWidth;
        pt_esp_2d_op->pfb_region.tSize.iHeight =  ESP_2D_PFB_SIZE / pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tSize.iWidth;
        pt_esp_2d_op->Row_priority_flag = 0;
    }
}

esp_2d_fsm_rt_t esp_2d_draw_DirtyRegion_screen0(esp_2d_op_t* pt_esp_2d_op){
    //else{
        if((pt_esp_2d_op->pfb_region.tLocation.iY + pt_esp_2d_op->pfb_region.tSize.iHeight) > (pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tLocation.iY 
                                                + pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tSize.iHeight)){
            pt_esp_2d_op->pfb_region.tSize.iHeight = pt_esp_2d_op->pfb_region.tSize.iHeight - ((pt_esp_2d_op->pfb_region.tLocation.iY + pt_esp_2d_op->pfb_region.tSize.iHeight) - (pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tLocation.iY 
                                                + pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tSize.iHeight));
        }
        esp_2d_Disp0_DrawBitmap (pt_esp_2d_op->pfb_region.tLocation.iX, 
                                 pt_esp_2d_op->pfb_region.tLocation.iY, 
                                 pt_esp_2d_op->pfb_region.tSize.iWidth, 
                                 pt_esp_2d_op->pfb_region.tSize.iHeight, 
                                 (uint8_t *)pt_esp_2d_op->pfb_data);
        
        pt_esp_2d_op->pfb_region.tLocation.iY += pt_esp_2d_op->pfb_region.tSize.iHeight; //my_2D_op.pfb_size.iHeight;
        if(pt_esp_2d_op->pfb_region.tLocation.iY >= (pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tLocation.iY 
                                                + pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tSize.iHeight)){
            //my_2D_op.state = 0;	
            //return esp_2d_fsm_rt_cpl;
            pt_esp_2d_op->DirtyRegions_run_num++;
            if(pt_esp_2d_op->DirtyRegions_run_num >= pt_esp_2d_op->DirtyRegions_num){
                //my_2D_op.state = 0;	
                pt_esp_2d_op->DirtyRegions_run_num = 0;
                //calculate_pfb_DirtyRegion();  
                return esp_2d_fsm_rt_cpl;
            }                                            
            calculate_pfb_DirtyRegion(pt_esp_2d_op);                                        
        }
    //}
    return esp_2d_fsm_rt_on_going;
}
esp_2d_fsm_rt_t esp_2d_draw_DirtyRegion_screen1(esp_2d_op_t* pt_esp_2d_op){
    
    //if(1 == my_2D_op.Row_priority_flag){
        esp_2d_region_t RegionOut;
        esp_2d_region_intersect(  &pt_esp_2d_op->pfb_region ,
                                &pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num],
                                &RegionOut);
        esp_2d_Disp0_DrawBitmap (RegionOut.tLocation.iX, 
             RegionOut.tLocation.iY, 
             RegionOut.tSize.iWidth, 
             RegionOut.tSize.iHeight, 
             (uint8_t *)pt_esp_2d_op->pfb_data);
        
        pt_esp_2d_op->pfb_region.tLocation.iX +=  pt_esp_2d_op->pfb_region.tSize.iWidth;//   my_2D_op.pfb_size.iWidth;
        if(pt_esp_2d_op->pfb_region.tLocation.iX >= (pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tLocation.iX 
                                                    + pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tSize.iWidth)){
            pt_esp_2d_op->pfb_region.tLocation.iX = pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tLocation.iX ;                
            pt_esp_2d_op->pfb_region.tLocation.iY += pt_esp_2d_op->pfb_region.tSize.iHeight; //my_2D_op.pfb_size.iHeight;
            if(pt_esp_2d_op->pfb_region.tLocation.iY >= (pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tLocation.iY 
                                                    + pt_esp_2d_op->ptDirtyRegions[pt_esp_2d_op->DirtyRegions_run_num].tSize.iHeight)){
                //my_2D_op.state = 0;	
                //return esp_2d_fsm_rt_cpl;
                pt_esp_2d_op->DirtyRegions_run_num++;
                if(pt_esp_2d_op->DirtyRegions_run_num >= pt_esp_2d_op->DirtyRegions_num){
                    //my_2D_op.state = 0;	
                    pt_esp_2d_op->DirtyRegions_run_num = 0;
                    //calculate_pfb_DirtyRegion();  
                    return esp_2d_fsm_rt_cpl;
                }                                            
                calculate_pfb_DirtyRegion(pt_esp_2d_op);                                        
            }
        }
    //}
    return esp_2d_fsm_rt_on_going;
}

typedef esp_2d_fsm_rt_t esp_2d_draw_DirtyRegion_screen_fn(esp_2d_op_t* pt_esp_2d_op);
esp_2d_draw_DirtyRegion_screen_fn * const esp_2d_draw_DirtyRegion_screen_fn_num[2] = {
    &esp_2d_draw_DirtyRegion_screen0,
    &esp_2d_draw_DirtyRegion_screen1,
};
#endif

esp_2d_fsm_rt_t esp_2d_scene_player_task(esp_2d_op_t *pt_esp_2d_op){
    enum {
        START = 0,
        DRAW_FRAME_START,//绘图框开始
        DRAW_BACKGROUND_PREPARE,//绘制背景准备
        DRAW_BACKGROUND,//绘制背景
        DRAW_SCENE_PREPARE,//绘制场景准备
        DRAW_SCENE,//绘制场景
        POST_SCENE_CHECK,//现场后检查

        SWITCH_SCENE_PREPARE,//切换场景准备
        SWITCH_SCENE,//切换场景
        SWITCH_SCENE_POST,//切换场景桩
    };
    //static char flag = 0;
    switch(pt_esp_2d_op->state){
        case START:
#if ESP_2D_DIRTY_REGIONS_ENABLE              
            if(pt_esp_2d_op->DirtyRegions_num){
                calculate_pfb_DirtyRegion(pt_esp_2d_op);
            }else{
                pt_esp_2d_op->pfb_region.tLocation.iY = 0;
                pt_esp_2d_op->pfb_region.tLocation.iX = 0;
                pt_esp_2d_op->pfb_region.tSize.iWidth = ESP_2D_PFB_WIDTH;
                pt_esp_2d_op->pfb_region.tSize.iHeight = ESP_2D_PFB_HEIGHT;
            }
        
#else        
                pt_esp_2d_op->pfb_region.tLocation.iY = 0;
                pt_esp_2d_op->pfb_region.tLocation.iX = 0;
                pt_esp_2d_op->pfb_region.tSize.iWidth = ESP_2D_PFB_WIDTH;
                pt_esp_2d_op->pfb_region.tSize.iHeight = ESP_2D_PFB_HEIGHT;
#endif        

            //my_2D_op.state = DRAW_SCENE_PREPARE;
            //break;
            if(pt_esp_2d_op->background_draw_flag){
                pt_esp_2d_op->state = DRAW_SCENE_PREPARE;
                //break;
            }else{
                pt_esp_2d_op->pfb_region.tLocation.iY = 0;
                pt_esp_2d_op->pfb_region.tLocation.iX = 0;
                pt_esp_2d_op->pfb_region.tSize.iWidth = ESP_2D_PFB_WIDTH;
                pt_esp_2d_op->pfb_region.tSize.iHeight = ESP_2D_PFB_HEIGHT;
                pt_esp_2d_op->state = DRAW_BACKGROUND_PREPARE;//DRAW_BACKGROUND_PREPARE;
            }                
            //break;
        case  DRAW_BACKGROUND_PREPARE:
            if(0 == pt_esp_2d_op->background_draw_flag){
                pt_esp_2d_op->state = DRAW_BACKGROUND;
                
            }
        //break;
        case  DRAW_BACKGROUND:
            if(0 == pt_esp_2d_op->background_draw_flag){
                pt_esp_2d_op->scene->fnScene(pt_esp_2d_op,pt_esp_2d_op->bIsNewFrame);
                if(esp_2d_fsm_rt_cpl == esp_2d_draw_all_screen(pt_esp_2d_op)){
                    pt_esp_2d_op->state = DRAW_SCENE_PREPARE;
                    pt_esp_2d_op->background_draw_flag = 1;
#if ESP_2D_DIRTY_REGIONS_ENABLE                      
                    if(pt_esp_2d_op->DirtyRegions_num){
                        calculate_pfb_DirtyRegion(pt_esp_2d_op);
                    }
#endif                    
                }
            }
        break;
        case DRAW_SCENE_PREPARE:
            pt_esp_2d_op->scene->fnOnFrameStart(pt_esp_2d_op,pt_esp_2d_op->scene);
#if ESP_2D_NAVIGATION_SCENE_ENABLE        
            pt_esp_2d_op->navigation_scene->fnOnFrameStart(pt_esp_2d_op,pt_esp_2d_op->navigation_scene);
#endif
            pt_esp_2d_op->state = DRAW_SCENE;	
            //break;
        case DRAW_SCENE:
            calculate_fps_time(1) ;
            pt_esp_2d_op->scene->fnScene(pt_esp_2d_op,pt_esp_2d_op->bIsNewFrame); 
#if ESP_2D_NAVIGATION_SCENE_ENABLE        
            pt_esp_2d_op->navigation_scene->fnScene(pt_esp_2d_op,pt_esp_2d_op->bIsNewFrame); 
#endif
#if ESP_2D_DIRTY_REGIONS_ENABLE         
            if(pt_esp_2d_op->DirtyRegions_num){
                //my2d_draw_DirtyRegion_screen();//======================================
                if(esp_2d_fsm_rt_cpl == (*esp_2d_draw_DirtyRegion_screen_fn_num[pt_esp_2d_op->Row_priority_flag])(pt_esp_2d_op)){
                    pt_esp_2d_op->state = 0;
                    calculate_fps_time(2) ;        
                    calculate_fps_time(3) ;
                }
            }else{
                if(esp_2d_fsm_rt_cpl == esp_2d_draw_all_screen(pt_esp_2d_op)){
                    pt_esp_2d_op->state = 0;
                    calculate_fps_time(2) ;
                    calculate_fps_time(3) ;
                }
            }
#else
            if(esp_2d_fsm_rt_cpl == esp_2d_draw_all_screen(pt_esp_2d_op)){
                pt_esp_2d_op->state = 0;
                calculate_fps_time(2) ;
                calculate_fps_time(3) ;
            }
#endif        
            if(pt_esp_2d_op->state != 0){
                calculate_fps_time(2) ;
            }
            break;
        case SWITCH_SCENE:
            pt_esp_2d_op->background_draw_flag = 0;
        break;
    }
    return esp_2d_fsm_rt_on_going;
}




void esp_2d_Disp0_DrawBitmap (uint32_t x, 
                            uint32_t y, 
                            uint32_t width, 
                            uint32_t height, 
                            const uint8_t *bitmap) 
{
    lcd_color_fill(x, y,  width ,  height , (uint16_t *)bitmap);
}

//=====================================================

